<template>
  <div class="video-section">
    <div class="hot-list">
      <div class="hot-list-header">热门景点</div>
      <div class="hot-list-wrapper">
        <ul>
          <li v-for="(spot, index) in hotSpots" :key="index" @click="exchangeChannel(spot.deviceChannelId)"
              :style="{
        backgroundColor: spot.deviceChannelId === id ? 'rgb(139,109,71)' : '',
        color: spot.deviceChannelId === id ? 'white' : ''
      }"
          >
            <span class="rank" :style="{
        color: spot.deviceChannelId === id ? 'white' : ''
      }">{{ String(index + 1).padStart(2, '0') }}</span>
            {{ spot.channelName }}
          </li>
        </ul>
      </div>
    </div>
    <div class="video-wrapper">
      <div class="video-container">
        <video
            ref="videoRef"
            muted
            autoplay
            controls
            controlsList="nodownload nofullscreen noremoteplayback noplaybackrate"
            disablePictureInPicture
        ></video>
        <div v-if="loading" class="video-loading">
          <span>正在连接直播...</span>
        </div>
        <div v-if="error" class="video-error">
          <span>{{ error }}</span>
          <button @click="retryPlay">重试</button>
        </div>
      </div>
      <div class="control-bar">
        <div class="online-stats">
          <span>当前在线：{{ channelCount.onlineCount }} 人</span>
          <span>历史累计：{{ channelCount.historyCount }} 人</span>
        </div>
        <div class="stream-switch">
          <!--          <button-->
          <!--            :class="{ active: streamType === 'mp4' }"-->
          <!--            @click="switchStream('mp4')"-->
          <!--          >-->
          <!--            MP4直播-->
          <!--          </button>-->
          <!--          <button-->
          <!--            :class="{ active: streamType === 'webrtc' }"-->
          <!--            @click="switchStream('webrtc')"-->
          <!--          >-->
          <!--            WebRTC直播-->
          <!--          </button>-->
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import {ref, onMounted, onUnmounted, defineProps} from 'vue'
import Hls from 'hls.js'
import {FrontApi} from "@/api/front";
// 默认的视频id
const videoRef = ref(null)
const ws = ref(null)
const mediaSource = ref(null)
const sourceBuffer = ref(null)
const playNumber = ref(369)
const userViewNumber = ref(1)
const loading = ref(true)
const error = ref('')
const isPlaying = ref(false)
const isMuted = ref(true)
const streamType = ref('mp4')
const hlsPlayer = ref(null)
const peerConnection = ref(null)
const webrtcPlayer = ref(null)
const id = ref();
const hotSpots = ref([]);
const channelCount = ref({onlineCount:0,historyCount:0});


function exchangeChannel(deviceChannelId) {
  id.value = deviceChannelId;
  console.log("id=>{}", id.value);
  // 设置 id 的值
  id.value = deviceChannelId;
  console.log("id => {}", id.value);

  // 动态获取设备类型（假设设备类型存储在某个变量或通过函数获取）
  const deviceType = getDeviceType(); // 假设 getDeviceType() 是获取设备类型的函数

  // 构造 WebSocket 的 URL
  const wsUrl = `ws://localhost:8080/ws/${deviceChannelId}/${deviceType}`;
  // 创建 WebSocket 连接
  const socket = new WebSocket(wsUrl);
  // WebSocket 连接成功
  socket.onopen = function (event) {
    console.log("WebSocket 连接成功:", wsUrl);

  };

  // WebSocket 连接错误
  socket.onerror = function (error) {
    console.error("WebSocket 错误:", error);
  };

  socket.onmessage = function (event) {
   var response = JSON.parse(event.data)
    channelCount.value.onlineCount = response.onlineCount
    channelCount.value.historyCount = response.historyCount
  }

  console.log("id=>{}",id.value)
  initPlayer();

 /* const tem = FrontApi.getChannelCount(deviceChannelId);
  tem.then(res => { channelCount.value.onlineCount=res.data.onlineCount
           channelCount.value.historyCount = res.data.historyCount}
  )*/


}

function getDeviceType() {
  // 获取浏览器的 userAgent 字符串
  const userAgent = navigator.userAgent.toLowerCase();

  // 判断设备类型
  if (/mobile|android|iphone|ipod|windows phone/i.test(userAgent)) {
    return "Phone "; // 移动设备
  } else if (/tablet|ipad|playbook|silk/i.test(userAgent)) {
    return "Phone"; // 平板设备
  } else {
    return "Pc"; // 桌面设备
  }
}
const initPlayer = async () => {
  console.log("id.value{}", id.value)
  if (videoRef.value) {
    loading.value = true
    error.value = ''

    try {
      const token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIxNiIsInNrIjoiNzIyNDQ5NTQ3ZTdhZmIwYWE4M2Q0MTMyYjg4NjUzZTkiLCJhayI6IjY3NDk0MTU4YzAwMGQwMWI0YmZjNzExNCIsImV4cCI6MTc2NzExMDQwMCwiaWF0IjoxNzMyODU0MTA0LCJhaWQiOiJJYmJ4MkZBZlg5a1NZNmtXNG9yYm1BPT0ifQ.IxK7Y5sRe1eeSjh-te5h99IGjuMzaOG82cc2dp80_KA'

      const response = await fetch(`/api/flowmedia/smv/deviceChannel/streamUrl?id=` + id.value + `&streamType=0&isWlan=true`, {
        method: 'GET',
        headers: {
          'Content-Type': 'application/json',
          'Accept': 'application/json',
          'token': token
        }
      })

      if (!response.ok) {
        throw new Error(`请求失败: ${response.status}`)
      }

      const data = await response.json()
      console.log('API响应数据:', data)

      if (!data || !data.data || !data.data.videoPreviewDto) {
        throw new Error('获取流地址失败：返回数据格式错误')
      }

      playNumber.value = data.data.playNumber || 0
      userViewNumber.value = data.data.userViewNumber || 0

      if (streamType.value === 'mp4') {
        if (!data.data.videoPreviewDto.wsFmp4Url) {
          throw new Error('获取MP4流地址失败')
        }
        const wsUrl = data.data.videoPreviewDto.wsFmp4Url.replace('10.140.244.152', '60.255.146.185')
        console.log('获取到的MP4流地址:', wsUrl)
        await initMP4Stream(wsUrl)
      } else {
        // 使用WebRTC
        const webrtcUrl = data.data.videoPreviewDto.webrtcUrl.replace('10.140.244.152', '60.255.146.185')
        console.log('获取到的WebRTC地址:', webrtcUrl)
        await initWebRTCStream(webrtcUrl)
      }

    } catch (err) {
      console.error('初始化播放器失败:', err)
      error.value = err.message || '初始化失败，请刷新页面重试'
      loading.value = false
    }
  }
}

const initMP4Stream = async (wsUrl) => {
  mediaSource.value = new MediaSource()
  videoRef.value.src = URL.createObjectURL(mediaSource.value)

  mediaSource.value.addEventListener('sourceopen', () => {
    console.log('MediaSource已打开')

    try {
      // 使用基础的H.264编解码器配置
      const mimeCodec = 'video/mp4; codecs="avc1.42E01E,mp4a.40.2"'
      console.log('使用编解码器:', mimeCodec)

      if (!MediaSource.isTypeSupported(mimeCodec)) {
        throw new Error(`不支持的编解码器: ${mimeCodec}`)
      }

      sourceBuffer.value = mediaSource.value.addSourceBuffer(mimeCodec)
      sourceBuffer.value.mode = 'segments'

      // 连接WebSocket
      ws.value = new WebSocket(wsUrl)
      ws.value.binaryType = 'arraybuffer'

      ws.value.onopen = () => {
        console.log('WebSocket已连接')
        loading.value = false
      }

      let queue = []
      let isFirstChunk = true
      let hasInitSegment = false
      let initSegment = null
      let isProcessing = false

      const processQueue = async () => {
        if (isProcessing || queue.length === 0) return

        if (!sourceBuffer.value || sourceBuffer.value.updating) {
          setTimeout(processQueue, 10)
          return
        }

        isProcessing = true

        try {
          while (queue.length > 0 && !sourceBuffer.value.updating) {
            const chunk = queue.shift()
            if (chunk) {
              await new Promise((resolve, reject) => {
                try {
                  sourceBuffer.value.appendBuffer(chunk)
                  const updateEndHandler = () => {
                    sourceBuffer.value.removeEventListener('updateend', updateEndHandler)
                    resolve()
                  }
                  sourceBuffer.value.addEventListener('updateend', updateEndHandler)
                } catch (err) {
                  if (err.name === 'QuotaExceededError') {
                    // 清理旧的缓冲区
                    if (sourceBuffer.value.buffered.length > 0) {
                      const start = sourceBuffer.value.buffered.start(0)
                      const end = sourceBuffer.value.buffered.end(0)
                      if (end - start > 10) {
                        sourceBuffer.value.remove(start, end - 10)
                        // 重新加入队列头部
                        queue.unshift(chunk)
                      }
                    }
                  }
                  reject(err)
                }
              })
            }
          }
        } catch (err) {
          console.error('处理队列数据失败:', err)
        } finally {
          isProcessing = false
          // 如果队列还有数据，继续处理
          if (queue.length > 0) {
            setTimeout(processQueue, 10)
          }
        }
      }

      sourceBuffer.value.addEventListener('updateend', () => {
        if (!isPlaying.value && videoRef.value.readyState >= 2 && hasInitSegment) {
          videoRef.value.play()
              .then(() => {
                isPlaying.value = true
                console.log('播放开始')
              })
              .catch(err => {
                console.error('播放失败:', err)
                if (err.name === 'NotAllowedError') {
                  error.value = '请点击播放按钮开始播放'
                }
              })
        }
        // 继续处理队列
        if (queue.length > 0) {
          processQueue()
        }
      })

      ws.value.onmessage = async (event) => {
        if (sourceBuffer.value && mediaSource.value.readyState === 'open') {
          try {
            const data = new Uint8Array(event.data)

            if (isFirstChunk) {
              console.log('收到第一个数据块:', data)
              // 检查是否是有效的MP4头
              if (data[4] === 0x66 && data[5] === 0x74 && data[6] === 0x79 && data[7] === 0x70) {
                console.log('检测到有效的MP4头')
                hasInitSegment = true
                initSegment = data
                queue.push(data)
                processQueue()
              }
              isFirstChunk = false
            } else {
              queue.push(event.data)
              if (!isProcessing) {
                processQueue()
              }
            }
          } catch (err) {
            console.error('处理数据失败:', err, mediaSource.value.readyState)
          }
        }
      }

      ws.value.onerror = (err) => {
        console.error('WebSocket错误:', err)
        error.value = 'WebSocket连接错误，请重试'
        loading.value = false
      }

      ws.value.onclose = () => {
        console.log('WebSocket已关闭')
        if (!isPlaying.value) {
          error.value = 'WebSocket连接已关闭，请重试'
          loading.value = false
        }
      }

    } catch (err) {
      console.error('创建SourceBuffer失败:', err)
      error.value = '创建播放器失败，请重试'
      loading.value = false
    }
  })

  // 监听视频元素事件
  videoRef.value.addEventListener('loadedmetadata', () => {
    console.log('视频元数据已加载:', {
      width: videoRef.value.videoWidth,
      height: videoRef.value.videoHeight,
      duration: videoRef.value.duration
    })
  })

  videoRef.value.addEventListener('playing', () => {
    console.log('视频开始播放，尺寸:', {
      width: videoRef.value.videoWidth,
      height: videoRef.value.videoHeight
    })
  })
}

const initWebRTCStream = async (webrtcUrl) => {
  try {
    // 清理旧的连接
    if (peerConnection.value) {
      peerConnection.value.close()
      peerConnection.value = null
    }

    // 创建新的 RTCPeerConnection
    const configuration = {
      iceServers: [
        {urls: 'stun:stun.l.google.com:19302'}
      ]
    }

    peerConnection.value = new RTCPeerConnection(configuration)

    // 监听ICE候选
    peerConnection.value.onicecandidate = event => {
      if (event.candidate) {
        console.log('发送ICE候选:', event.candidate)
      }
    }

    // 监听连接状态
    peerConnection.value.onconnectionstatechange = () => {
      console.log('WebRTC连接状态:', peerConnection.value.connectionState)
      if (peerConnection.value.connectionState === 'connected') {
        loading.value = false
        console.log('WebRTC连接成功')
      } else if (peerConnection.value.connectionState === 'failed') {
        error.value = 'WebRTC连接失败，请重试'
        loading.value = false
      }
    }

    // 监听流
    peerConnection.value.ontrack = event => {
      console.log('收到媒体流:', event.streams[0])
      if (videoRef.value && event.streams[0]) {
        videoRef.value.srcObject = event.streams[0]
        videoRef.value.play()
            .then(() => {
              isPlaying.value = true
              console.log('WebRTC流播放开始')
            })
            .catch(err => {
              console.error('播放失败:', err)
              if (err.name === 'NotAllowedError') {
                error.value = '请点击播放按钮开始播放'
              }
            })
      }
    }

    // 创建新的WebSocket连接用于WebRTC信令
    const rtcWs = new WebSocket(webrtcUrl)
    rtcWs.onopen = async () => {
      console.log('WebRTC信令服务器已连接')

      try {
        // 创建offer
        const offer = await peerConnection.value.createOffer({
          offerToReceiveAudio: true,
          offerToReceiveVideo: true
        })

        await peerConnection.value.setLocalDescription(offer)

        // 发送offer到信令服务器
        rtcWs.send(JSON.stringify({
          type: 'offer',
          sdp: offer.sdp
        }))
      } catch (err) {
        console.error('创建offer失败:', err)
        error.value = '创建连接失败，请重试'
        loading.value = false
      }
    }

    rtcWs.onmessage = async event => {
      try {
        const message = JSON.parse(event.data)
        console.log('收到WebRTC信令消息:', message)

        if (message.type === 'answer') {
          const answer = new RTCSessionDescription({
            type: 'answer',
            sdp: message.sdp
          })
          await peerConnection.value.setRemoteDescription(answer)
        } else if (message.type === 'candidate') {
          const candidate = new RTCIceCandidate(message.candidate)
          await peerConnection.value.addIceCandidate(candidate)
        }
      } catch (err) {
        console.error('处理WebRTC信令消息失败:', err)
      }
    }

    rtcWs.onerror = err => {
      console.error('WebRTC信令服务器错误:', err)
      error.value = '连接WebRTC信令服务器失败'
      loading.value = false
    }

    rtcWs.onclose = () => {
      console.log('WebRTC信令服务器连接已关闭')
      if (!isPlaying.value) {
        error.value = 'WebRTC信令服务器连接已关闭'
        loading.value = false
      }
    }

  } catch (err) {
    console.error('初始化WebRTC流失败:', err)
    error.value = err.message || '初始化WebRTC流失败，请重试'
    loading.value = false
  }
}

const destroyPlayer = () => {
  return new Promise((resolve) => {
    isPlaying.value = false
    loading.value = true
    error.value = ''

    if (streamType.value === 'webrtc') {
      // 清理WebRTC连接
      if (peerConnection.value) {
        peerConnection.value.close()
        peerConnection.value = null
      }
      resolve()
    } else {
      // 清理WebSocket连接（MP4流）
      if (ws.value) {
        ws.value.onclose = () => {
          console.log('WebSocket已正常关闭')
          ws.value = null
          resolve()
        }
        ws.value.close()
      } else {
        resolve()
      }
    }

    // 清理视频元素
    if (videoRef.value) {
      try {
        videoRef.value.pause()
        if (videoRef.value.srcObject) {
          videoRef.value.srcObject.getTracks().forEach(track => track.stop())
          videoRef.value.srcObject = null
        }
        videoRef.value.src = ''
        videoRef.value.load()

        // 移除所有事件监听器
        const clone = videoRef.value.cloneNode(true)
        if (videoRef.value.parentNode) {
          videoRef.value.parentNode.replaceChild(clone, videoRef.value)
        }
        videoRef.value = clone
      } catch (err) {
        console.warn('重置视频元素时发生错误:', err)
      }
    }

    // 清理MediaSource相关资源
    if (sourceBuffer.value) {
      try {
        if (mediaSource.value && mediaSource.value.readyState === 'open') {
          sourceBuffer.value.abort()
        }
      } catch (err) {
        console.warn('中止SourceBuffer时发生错误:', err)
      }
      sourceBuffer.value = null
    }

    if (mediaSource.value) {
      try {
        if (mediaSource.value.readyState === 'open') {
          mediaSource.value.endOfStream()
        }
      } catch (err) {
        console.warn('结束MediaSource时发生错误:', err)
      }
      mediaSource.value = null
    }
  })
}

const switchStream = async (type) => {
  if (type === streamType.value) return

  // 先更新类型，再清理资源
  const oldType = streamType.value
  streamType.value = type

  try {
    // 等待资源清理完成
    await destroyPlayer()

    // 添加小延时确保所有资源都被正确释放
    await new Promise(resolve => setTimeout(resolve, 500))

    await initPlayer()
  } catch (err) {
    console.error('切换流类型失败:', err)
    // 如果切换失败，恢复到原来的类型
    streamType.value = oldType
    error.value = '切换失败，请重试'
    loading.value = false
  }
}

const retryPlay = async () => {
  await destroyPlayer()
  await new Promise(resolve => setTimeout(resolve, 500))
  await initPlayer()
}

const togglePlay = async () => {
  if (videoRef.value) {
    if (videoRef.value.paused) {
      await videoRef.value.play()
      isPlaying.value = true
    } else {
      videoRef.value.pause()
      isPlaying.value = false
    }
  }
}

const toggleMute = () => {
  if (videoRef.value) {
    videoRef.value.muted = !videoRef.value.muted
    isMuted.value = videoRef.value.muted
  }
}

const concatUint8Arrays = (a, b) => {
  const c = new Uint8Array(a.length + b.length)
  c.set(a, 0)
  c.set(b, a.length)
  return c
}
const sortData = async () => {
  const res2 = await FrontApi.getChannelList();
  if (res2) {
    hotSpots.value = res2.data;
    id.value = hotSpots.value[0].deviceChannelId;
  }
}
onMounted(async () => {
  await sortData();
  await initPlayer();

})

onUnmounted(async () => {
  await destroyPlayer()
})
</script>

<style scoped>
.video-section {
  display: flex;
  gap: 20px;
  margin-bottom: 20px;
}

.hot-list {
  width: 250px;
  flex-shrink: 0;
  background: #fff;
  border-radius: 4px;
  border: 1px solid #ddd;
}

.hot-list-header {
  padding: 10px 15px;
  border-bottom: 1px solid #ddd;
  font-weight: bold;
  background: #fff;
}

.hot-list-wrapper {
  height: 400px;
  overflow-y: auto;
}

.hot-list ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

.hot-list li {

  padding: 12px 15px;
  border-bottom: 1px solid #eee;
  cursor: pointer;
  display: flex;
  align-items: center;
  transition: all 0.3s ease;
}

.hot-list li:hover {
  background: #f5f5f5;
  color: #8b6d47;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.hot-list li .rank {

  margin-right: 10px;
  font-weight: bold;
  color: #999;
  width: 24px;

}

.hot-list li:nth-child(1) .rank,
.hot-list li:nth-child(2) .rank,
.hot-list li:nth-child(3) .rank {
  color: #8b6d47;
}

.video-wrapper {
  flex: 1;
  background-color: #333;
  border-radius: 4px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.video-container {
  width: 100%;
  height: 400px;
  position: relative;
}

.video-container video {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: #000;
}

.control-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px 20px;
  background: #333;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
}

.stream-switch {
  display: flex;
  gap: 10px;
}

.stream-switch button {
  padding: 8px 16px;
  border: 1px solid #8b6d47;
  border-radius: 4px;
  background: transparent;
  color: white;
  cursor: pointer;
  transition: all 0.3s;
  font-size: 14px;
}

.stream-switch button:hover {
  background: rgba(139, 109, 71, 0.3);
}

.stream-switch button.active {
  background: #8b6d47;
  border-color: #8b6d47;
}

.online-stats {
  color: coral;
  margin: 0;
}

.video-loading,
.video-error {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.7);
  color: white;
  font-size: 14px;
}

.video-error button {
  margin-top: 10px;
  padding: 5px 15px;
  border: none;
  border-radius: 4px;
  background: #8b6d47;
  color: white;
  cursor: pointer;
  transition: background 0.3s;
}

.video-error button:hover {
  background: #a58057;
}

.custom-controls {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  background: rgba(0, 0, 0, 0.5);
  padding: 10px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  opacity: 0;
  transition: opacity 0.3s;
}

.video-container:hover .custom-controls {
  opacity: 1;
}

.custom-controls button {
  background: transparent;
  border: 1px solid #fff;
  color: #fff;
  padding: 5px 15px;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.3s;
}

.custom-controls button:hover {
  background: rgba(255, 255, 255, 0.1);
}

.video-container video::-webkit-media-controls {
  display: none !important;
}

.video-container video::-webkit-media-controls-enclosure {
  display: none !important;
}

.video-container video::-webkit-media-controls-panel {
  display: none !important;
}

.video-container video::-webkit-media-controls-overlay-play-button {
  display: none !important;
}

.video-container video::-webkit-media-controls-timeline {
  display: none !important;
}

.video-container video::-webkit-media-controls-current-time-display,
.video-container video::-webkit-media-controls-time-remaining-display {
  display: none !important;
}

.video-container video::-webkit-media-controls-mute-button,
.video-container video::-webkit-media-controls-volume-slider {
  display: none !important;
}

.video-container video::-webkit-media-controls-fullscreen-button {
  display: none !important;
}

@media (max-width: 768px) {
  .video-section {
    flex-direction: column;
  }

  .video-wrapper {
    order: 1;
  }

  .online-stats {
    color: coral;
    order: 2;
    margin: 10px 0;
  }

  .hot-list {
    width: 100%;
    order: 3;
  }

  .hot-list-wrapper {
    height: auto;
    max-height: 300px;
  }

  .hot-list ul {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 10px;
    padding: 10px;
  }

  .hot-list li {
    border: 1px solid #eee;
    border-radius: 4px;
    margin: 0;
  }

  .video-container {
    height: 240px;
  }
}
</style>
